--[[
Title: myBigIgnite
Author: Istaran | Medivh - EU
Version: 3.5.4
Release date: 2013-09-10T15:51:41Z
myBigIgnite is licensed under GPLv3.
]]



--##############################################################################################################################################
-- ace addon creation and initialization -------------------------------------------------------------------------------------------------------

-- checks if mBI must be enabled at all
if select(2, UnitClass("player")) ~= "MAGE" then
   return
end

myBigIgnite = LibStub("AceAddon-3.0"):NewAddon("myBigIgnite", "AceConsole-3.0", "AceEvent-3.0")
local MBI = myBigIgnite

-- libraries initialization
local L = LibStub("AceLocale-3.0"):GetLocale("myBigIgnite", true)
local LSM = LibStub("LibSharedMedia-3.0")
local ACR = LibStub("AceConfigRegistry-3.0")

-- cache
local pairs, ipairs, type, tonumber, tostring, print, tinsert, tremove, wipe = pairs, ipairs, type, tonumber, tostring, print, tinsert, tremove, wipe
local strfind, strsub, floor, ceil, format = strfind, strsub, floor, ceil, format
local _

-- addon tables, constants and defaults
do
	--[===[@debug@
	MBI.VERSION = "3.5.3"
	--@end-debug@]===]
	MBI.VERSION = MBI.VERSION or GetAddOnMetadata("myBigIgnite", "Version")

	MBI.ORANGE = "|cffFF8000"
	MBI.YELLOW_LIGHT = "|cffFFE680"
	MBI.YELLOW = "|cffFFD101"
	MBI.NORMAL = "|cffFFFFFF"

	MBI.REFRESH = 0.1
	MBI.REFRESH_CM = 1

	MBI.F = {}
	MBI.remainTime = {}
	MBI.dotToTrack = {}
	MBI.dotIcon = {}
	MBI.dotName = {}
	MBI.dotOrder = {}
	
	MBI.dotIDs = {
		ignite = 12654,
		--livingBomb = 44457,
		--frostBomb = 112948,
		--arcaneBomb = 102455,
		pyroblast = 11366,
		combustion = 83853,
	}
	
	MBI.buffIDs = {
		heatingup = 48107,
		instapyro = 48108,
	}
	
	MBI.miscIDs = {
		masteryIgnite = 12846,
		combustion = 11129,
		inferno = 108853,
	}

	MBI.defaults = {
		profile = {
			general = {
				anchor = {
					coord = {
						xcd = UIParent:GetWidth() / 2,
						ycd = UIParent:GetHeight() / 2,
					},
					strata = 3,
					align = "CENTER",
				},
				autohide = {
					noCombat = true,
					noIgnite = false,
					combuCD = false,
					combuCDTime = 0,
				},
				layout = {
					textSize = 13,
					font = "Friz Quadrata TT",
					background = {
						enabled = true,
						texture = "Solid",
						darkness = 0.1,
					},
					border = {
						enabled = true,
						texture = "Solid",
					},
					bar = "BantoBar",
					alpha = 1,
					barTextSpecificColor = false,
					barTextColor = {
						r = 1,
						g = 0.9,
						b = 0.6,
					},
					iconTextColor = {
						r = 1,
						g = 0.9,
						b = 0.6,
					},
				},
				splashMsg = true,
				resetStats = 1,
			},
			ignite = {
				layout = {
					bgInset = 0.75,
					bdSize = 0.75,
					adjust = 1.5,
					text = {
						format = "condensed",
						align = "RIGHT",
						ofx = 0.75,
						ofy = 1.25,
					},
				},
				timer = {
					enabled = true,
					reverse = false,
					redZone = 1,
					alpha = 1,
					tick = true,
					redZoneColor = {
						r = 1,
						g = 0.2,
						b = 0,
					},
				},
				power = {
					enabled = true,
					align = "LEFT",
					alpha = 1,
					gradient = "rg",
					middle = 0.7,
					tableSize = 100,
				},
				dmgAsDps = false,
				useCombatLog = false,
				smoothDmgReport = true,
				smoothDmgValue = 0.6,
			},
			threshold = {
				value = 0,
				interm = {
					enabled = true,
					perct = 0.85,
				},
				low = {
					color = {
						r = 1,
						g = 0.5,
						b = 0,
					},
				},
				mid = {
					color = {
						r = 1,
						g = 1,
						b = 0,
					},
					mult = 1.1,
				},
				high = {
					color = {
						r = 0,
						g = 1,
						b = 0,
					},
					mult = 1.3,
				},
				forCombu = {
				},
			},
			modules = {
				general = {
					combustion = {
						enabled = true,
						position = "LEFT",
					},
					heatingup = {
						enabled = true,
						position = "BOTTOM",
						show = "both",
					},
					bomb = {
						enabled = false,
						position = "TOP",
					},
					offset = 9,
				},
				combustion = {
					enabled = true,
					size = 1.5,
					low = false,
					scaling = {
						enabled = true,
						mid = 1.1,
						high = 1.3,
					},
					scrollText = {
						color = {
							r = 1,
							g = 1,
							b = 0,
						},
						size = 1.3,
					},
					iconText = {
						dmgSize = 0.45,
						dmgOfx = 0,
						dmgOfy = -1.5,
						tickSize = 0.3,
						tickOfx = 0.5,
						tickOfy = 1,
						cdSize = 0.4,
						cdTextEnabled = false,
					},
					timer = {
						reverse = false,
						align = "bellow",
					},
				},
				heatingup = {
					enabled = true,
					size = 1.95,
					vertical = false,
					switch = false,
					highlight = true,
					texture = "fire",
					showHUPAlways = false,
					text = {
						enabled = true,
						anchor = "RIGHT",
						ofx = -4.5,
						ofy = -8,
						size = 0.3,
					},
				},
				bomb = {
					enabled = false,
				},
			},
		},
	}
end



--##############################################################################################################################################
-- loading process -----------------------------------------------------------------------------------------------------------------------------

-- on enable
function MBI:OnEnable()
	MBI:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED", "Load")
	MBI:RegisterEvent("PLAYER_LEVEL_UP", "Load")
	MBI:RegisterEvent("PLAYER_ENTERING_WORLD", "Load")
	MBI:LoadFakeOptions()
end

-- loads/unloads addon elements
function MBI:Load()
	-- loads components if player in fire spec, do nothing if already in
	if IsSpellKnown(MBI.miscIDs.masteryIgnite) and not MBI.specFire then
		local showHelp
		-- addon loading first time
		if not MBI.addonLoadded then
			-- addon settings update
			MBI:UpdateAddon()

			-- db and cmd
			MBI.db = LibStub("AceDB-3.0"):New("myBigIgnite_settings", MBI.defaults)
			MBI:RegisterChatCommand("mybigignite","CmdParser")
			MBI:RegisterChatCommand("mbi", "CmdParser")

			-- stats and power bar
			MBI:InitStatModule()
			MBI:InitPowerBar()
			
			-- update addon version in db if ncessary
			if not MBI.db.global.version or MBI.db.global.version < MBI.VERSION then
				if not MBI.db.global.version or string.match(MBI.db.global.version, "(%d+.%d+).%d+") < string.match(MBI.VERSION, "(%d+.%d+).%d+") then
					showHelp = true
				end
				MBI.db.global.version = MBI.VERSION
			end

			--shared media stuff
			LSM:Register("border", "Solid", "Interface\\Buttons\\WHITE8X8")

			local texturesPath = "Interface\\Addons\\myBigIgnite\\bars\\"
			LSM:Register("statusbar", "Aluminum", texturesPath .. "Aluminum.tga")
			LSM:Register("statusbar", "Armory", texturesPath .. "Armory.tga")
			LSM:Register("statusbar", "BantoBar", texturesPath .. "BantoBar.tga")
			LSM:Register("statusbar", "Charcoal", texturesPath .. "Charcoal.tga")
			LSM:Register("statusbar", "Flat", texturesPath .. "Flat.tga")
			LSM:Register("statusbar", "Frost", texturesPath .. "Frost.tga")
			LSM:Register("statusbar", "Glaze", texturesPath .. "Glaze.tga")
			LSM:Register("statusbar", "Gloss", texturesPath .. "Gloss.tga")
			LSM:Register("statusbar", "Graphite", texturesPath .. "Graphite.tga")
			LSM:Register("statusbar", "Healbot", texturesPath .. "Healbot.tga")
			LSM:Register("statusbar", "LiteStep", texturesPath .. "LiteStep.tga")
			LSM:Register("statusbar", "Minimalist", texturesPath .. "Minimalist.tga")
			LSM:Register("statusbar", "Otravi", texturesPath .. "Otravi.tga")
			LSM:Register("statusbar", "Perl", texturesPath .. "Perl.tga")
			LSM:Register("statusbar", "Rocks", texturesPath .. "Rocks.tga")
			LSM:Register("statusbar", "Runes", texturesPath .. "Runes.tga")
			LSM:Register("statusbar", "Shard", texturesPath .. "Shard.tga")
			LSM:Register("statusbar", "Smooth", texturesPath .. "Smooth.tga")
			LSM:Register("statusbar", "Striped", texturesPath .. "Striped.tga")
			LSM:Register("statusbar", "Xeon", texturesPath .. "Xeon.tga")

			-- addon font
			MBI.font = LSM:Fetch("font", MBI.db.profile.general.layout.font)

			-- event registring
			MBI:RegisterEvent("PLAYER_REGEN_DISABLED", "CombatCheck")
			MBI:RegisterEvent("PLAYER_REGEN_ENABLED", "CombatCheck")
			MBI:RegisterEvent("UI_SCALE_CHANGED", "ScaleChange")
			MBI:RegisterEvent("GLYPH_ADDED", "CombuGlyphed")
			MBI:RegisterEvent("GLYPH_REMOVED", "CombuGlyphed")

			-- creates general tables storing settings + frames
			MBI:CreateSpellTables()
			MBI:SetIgniteFrame()
			MBI:CreateOnUpdateFrame()
			MBI:SetCombustionFrame()
			MBI:SetHeatingUpFrame()

			MBI.addonLoadded = true

		-- back into active state
		else
			MBI:RegisterEvent("PLAYER_REGEN_DISABLED", "CombatCheck")
			MBI:RegisterEvent("PLAYER_REGEN_ENABLED", "CombatCheck")
			MBI:RegisterEvent("UI_SCALE_CHANGED", "ScaleChange")
			MBI:RegisterEvent("GLYPH_ADDED", "CombuGlyphed")
			MBI:RegisterEvent("GLYPH_REMOVED", "CombuGlyphed")
			MBI:RegisterChatCommand("mybigignite","CmdParser")
			MBI:RegisterChatCommand("mbi", "CmdParser")
			MBI.F.anchor:Show()
		end

		-- some var init
		MBI.time_before_stop_onupdate = 10
		MBI.smoothDmg = 0
		MBI.combuTotal = 0
		MBI.combuPredicted = 0
		MBI.combuBeforeHiding = 1
		
		-- combustion CD checking
		MBI:CombuCheck()
		
		-- combustion glyph check
		MBI:CombuGlyphed()

		-- config panel switches
		if MBI.configLoaded then
			MBI:ChangeConfigDisplay("fireSpec")
		else
			MBI:ChangeConfigDisplay("unloadedConfig")
		end

		-- splash message
		if MBI.db.profile.general.splashMsg then
			print(MBI.ORANGE .. L["myBigIgnite v"] .. MBI.VERSION .. L[" loaded."])
		end

		--warning if threshold unset
		if MBI.db.profile.threshold.value == 0 then
			print(MBI.ORANGE .. L["myBigIgnite: "] .. MBI.YELLOW_LIGHT .. L["notyetthreshold"])
		end

		-- hides MBI frame if required
		if MBI.db.profile.general.autohide.noCombat then
			MBI.F.main:Hide()
		else
			MBI.F.main:Show()
		end
		
		-- show help if necessary
		if showHelp then
			MBI:OpenInfo("help", true)
		end

		MBI.specFire = true

	-- unload when ignite unkown and was in fire spec
	elseif not IsSpellKnown(MBI.miscIDs.masteryIgnite) and MBI.specFire then
		MBI:UnregisterEvent("PLAYER_REGEN_DISABLED")
		MBI:UnregisterEvent("PLAYER_REGEN_ENABLED")
		MBI:UnregisterEvent("UI_SCALE_CHANGED")
		MBI:UnregisterEvent("GLYPH_ADDED")
		MBI:UnregisterEvent("GLYPH_REMOVED")
		MBI:UnregisterChatCommand("mybigignite")
		MBI:UnregisterChatCommand("mbi")
		MBI.F.anchor:Hide()

		-- splash message
		if MBI.db.profile.general.splashMsg then
			print(MBI.ORANGE .. L["myBigIgnite is disabled."])
		end

		-- non fire spec config panel state
		MBI:ChangeConfigDisplay("ooFireSpec")

		MBI.specFire = false

	-- load non fire spec config pannel if not in fire spec and wasn't previously
	elseif not IsSpellKnown(MBI.miscIDs.masteryIgnite) and not MBI.specFire then
		MBI:ChangeConfigDisplay("ooFireSpec")
	end
end

-- addon update
function MBI:UpdateAddon()
	-- erase user db when updating from version < 3.1.x
	if _G["mBIsettings"] and (not _G["mBIsettings"].global or not _G["mBIsettings"].global.version or _G["mBIsettings"].global.version < "3.1.0") then
		wipe(_G["mBIsettings"])
	end
	
	-- update from versions < 3.2.0
	if _G["mBIsettings"] and _G["mBIsettings"].global and _G["mBIsettings"].global.version < "3.2.0" then		
		for profile in pairs(_G["mBIsettings"].profiles) do
			
			_G["mBIsettings"].profiles[profile].general = _G["mBIsettings"].profiles[profile].general or {}
			_G["mBIsettings"].profiles[profile].general.layout = _G["mBIsettings"].profiles[profile].general.layout or {}
			
			if _G["mBIsettings"].profiles[profile].general.layout.background then
				local texture =_G["mBIsettings"].profiles[profile].general.layout.background
				_G["mBIsettings"].profiles[profile].general.layout.background = nil
				_G["mBIsettings"].profiles[profile].general.layout.background = {}
				_G["mBIsettings"].profiles[profile].general.layout.background.texture = texture
			end
			
			_G["mBIsettings"].profiles[profile].general.layout.background = _G["mBIsettings"].profiles[profile].general.layout.background or {}
			
			if _G["mBIsettings"].profiles[profile].ignite and _G["mBIsettings"].profiles[profile].ignite.layout and _G["mBIsettings"].profiles[profile].ignite.layout.background then
				if _G["mBIsettings"].profiles[profile].ignite.layout.background.enabled ~= nil then
					_G["mBIsettings"].profiles[profile].general.layout.background.enabled = _G["mBIsettings"].profiles[profile].ignite.layout.background.enabled
					_G["mBIsettings"].profiles[profile].ignite.layout.background.enabled = nil
				end
				if _G["mBIsettings"].profiles[profile].ignite.layout.background.darkness then
					_G["mBIsettings"].profiles[profile].general.layout.background.darkness = _G["mBIsettings"].profiles[profile].ignite.layout.background.darkness
					_G["mBIsettings"].profiles[profile].ignite.layout.background.darkness = nil
				end
				if _G["mBIsettings"].profiles[profile].ignite.layout.background.inset then
					_G["mBIsettings"].profiles[profile].ignite.layout.bgInset = _G["mBIsettings"].profiles[profile].ignite.layout.background.inset
					_G["mBIsettings"].profiles[profile].ignite.layout.background = nil
				end
			end
			
			if _G["mBIsettings"].profiles[profile].general.layout.border then
				local texture =_G["mBIsettings"].profiles[profile].general.layout.border
				_G["mBIsettings"].profiles[profile].general.layout.border = nil
				_G["mBIsettings"].profiles[profile].general.layout.border = {}
				_G["mBIsettings"].profiles[profile].general.layout.border.texture = texture
			end
			
			_G["mBIsettings"].profiles[profile].general.layout.border = _G["mBIsettings"].profiles[profile].general.layout.border or {}
			
			if _G["mBIsettings"].profiles[profile].ignite and _G["mBIsettings"].profiles[profile].ignite.layout and _G["mBIsettings"].profiles[profile].ignite.layout.border then
				if _G["mBIsettings"].profiles[profile].ignite.layout.border.enabled ~= nil then
					_G["mBIsettings"].profiles[profile].general.layout.border.enabled = _G["mBIsettings"].profiles[profile].ignite.layout.border.enabled
					_G["mBIsettings"].profiles[profile].ignite.layout.border.enabled = nil
				end
				if _G["mBIsettings"].profiles[profile].ignite.layout.border.size then
					_G["mBIsettings"].profiles[profile].ignite.layout.bdSize = _G["mBIsettings"].profiles[profile].ignite.layout.border.size 
					_G["mBIsettings"].profiles[profile].ignite.layout.border = nil
				end
			end
			
			if _G["mBIsettings"].profiles[profile].trackpyro ~= nil then
				_G["mBIsettings"].profiles[profile].trackpyro = nil
			end
			
			if _G["mBIsettings"].profiles[profile].stats and _G["mBIsettings"].profiles[profile].stats.info then
				local temp = {}
				for k, v in pairs(_G["mBIsettings"].profiles[profile].stats.info) do
					temp[k] = v
				end
				wipe(_G["mBIsettings"].profiles[profile].stats.info)
				_G["mBIsettings"].profiles[profile].stats.info.ignite = {}
				_G["mBIsettings"].profiles[profile].stats.info.ignite = MBI:DeepCopy(temp)
			end
		end
		
		-- database name changed introduced at 3.2.0
		_G["myBigIgnite_settings"] = {}
		_G["myBigIgnite_settings"] = MBI:DeepCopy(_G["mBIsettings"])
		_G["mBIsettings"] = nil
	end
	
	-- new updates since database name change
	if _G["myBigIgnite_settings"] and _G["myBigIgnite_settings"].global then
		-- updates from version < 3.4.0
		if _G["myBigIgnite_settings"].global.version < "3.4.0" then
			for profile in pairs(_G["myBigIgnite_settings"].profiles) do
				if _G["myBigIgnite_settings"].profiles[profile].modules and _G["myBigIgnite_settings"].profiles[profile].modules.combustion then
					if _G["myBigIgnite_settings"].profiles[profile].modules.combustion.bdSize then _G["myBigIgnite_settings"].profiles[profile].modules.combustion.bdSize = nil end
					if _G["myBigIgnite_settings"].profiles[profile].modules.combustion.bgInset then _G["myBigIgnite_settings"].profiles[profile].modules.combustion.bgInset = nil end
					if _G["myBigIgnite_settings"].profiles[profile].modules.combustion.adjust then _G["myBigIgnite_settings"].profiles[profile].modules.combustion.adjust = nil end
				end
			end
		end
		
		-- updates from version < 3.5.0
		if _G["myBigIgnite_settings"].global.version < "3.5.0" then
			for profile in pairs(_G["myBigIgnite_settings"].profiles) do
				if _G["myBigIgnite_settings"].profiles[profile].modules then
					_G["myBigIgnite_settings"].profiles[profile].modules.general = {}
					_G["myBigIgnite_settings"].profiles[profile].modules.general.combustion = {}
					_G["myBigIgnite_settings"].profiles[profile].modules.general.heatingup = {}
					
					if _G["myBigIgnite_settings"].profiles[profile].modules.heatingup then
						if _G["myBigIgnite_settings"].profiles[profile].modules.heatingup.position then _G["myBigIgnite_settings"].profiles[profile].modules.heatingup.position = nil end
						if _G["myBigIgnite_settings"].profiles[profile].modules.heatingup.enabled == false then
							_G["myBigIgnite_settings"].profiles[profile].modules.general.heatingup.enabled = false
							_G["myBigIgnite_settings"].profiles[profile].modules.heatingup.enabled = nil
						end
						if _G["myBigIgnite_settings"].profiles[profile].modules.heatingup.align then
							_G["myBigIgnite_settings"].profiles[profile].modules.heatingup.align = nil
						end
					end
					
					if _G["myBigIgnite_settings"].profiles[profile].modules.combustion then
						if _G["myBigIgnite_settings"].profiles[profile].modules.combustion.enabled == false then
							_G["myBigIgnite_settings"].profiles[profile].modules.general.combustion.enabled = false
							_G["myBigIgnite_settings"].profiles[profile].modules.combustion.enabled = nil
						end
						if _G["myBigIgnite_settings"].profiles[profile].modules.combustion.align and _G["myBigIgnite_settings"].profiles[profile].modules.combustion.align.anchor then
							_G["myBigIgnite_settings"].profiles[profile].modules.general.combustion.position = _G["myBigIgnite_settings"].profiles[profile].modules.combustion.align.anchor
							_G["myBigIgnite_settings"].profiles[profile].modules.combustion.align = nil
						end
					end
				end
			end
		end
	end
end

-- stat module init
function MBI:InitStatModule()
	MBI.db.profile.stats = MBI.db.profile.stats or {}
	MBI.db.profile.stats.info = MBI.db.profile.stats.info or {}
	MBI.db.profile.stats.info.ignite = MBI.db.profile.stats.info.ignite or {}
	MBI.db.profile.stats.info.combustion = MBI.db.profile.stats.info.combustion or {}
	
	MBI.db.profile.stats.info.combustion.averageDot = MBI.db.profile.stats.info.combustion.averageDot or 0
	MBI.db.profile.stats.info.combustion.dmgDot = MBI.db.profile.stats.info.combustion.dmgDot or 0
	MBI.db.profile.stats.info.combustion.countDot = MBI.db.profile.stats.info.combustion.countDot or 0
	MBI.db.profile.stats.info.combustion.highestDot = MBI.db.profile.stats.info.combustion.highestDot or 0
	MBI.db.profile.stats.info.combustion.lowestDot = MBI.db.profile.stats.info.combustion.lowestDot or 100000
	
	MBI.db.profile.stats.info.combustion.averageDirect = MBI.db.profile.stats.info.combustion.averageDirect or 0
	MBI.db.profile.stats.info.combustion.dmgDirect = MBI.db.profile.stats.info.combustion.dmgDirect or 0
	MBI.db.profile.stats.info.combustion.countDirect = MBI.db.profile.stats.info.combustion.countDirect or 0
	MBI.db.profile.stats.info.combustion.highestDirect = MBI.db.profile.stats.info.combustion.highestDirect or 0
	MBI.db.profile.stats.info.combustion.lowestDirect = MBI.db.profile.stats.info.combustion.lowestDirect or 100000
	
	MBI.db.profile.stats.info.ignite.average = MBI.db.profile.stats.info.ignite.average or 0
	MBI.db.profile.stats.info.ignite.dmg = MBI.db.profile.stats.info.ignite.dmg or 0
	MBI.db.profile.stats.info.ignite.count = MBI.db.profile.stats.info.ignite.count or 0
	MBI.db.profile.stats.info.ignite.highest = MBI.db.profile.stats.info.ignite.highest or 0
	MBI.db.profile.stats.info.ignite.lowest = MBI.db.profile.stats.info.ignite.lowest or 100000
	MBI.db.profile.stats.info.ignite.supOptT = MBI.db.profile.stats.info.ignite.supOptT or 0
	MBI.db.profile.stats.info.ignite.supIntermT = MBI.db.profile.stats.info.ignite.supIntermT or 0
	MBI.db.profile.stats.info.ignite.thresholdCount = MBI.db.profile.stats.info.ignite.thresholdCount or 0
end

-- power bar init
function MBI:InitPowerBar()
	MBI.db.profile.stats.power = MBI.db.profile.stats.power or {}
	MBI.power = {}
	
	-- check integrity of value table + init of average and sigma value
	if #MBI.db.profile.stats.power > 0 then
		while #MBI.db.profile.stats.power > MBI.db.profile.ignite.power.tableSize do
			tremove(MBI.db.profile.stats.power, 1)
		end
		MBI:CalculatePower()
	else
		MBI.power.average = 0
		MBI.power.sigma = 0
	end
end

-- we create a table containining auras to be scanned on the target and on the player with all the informations
function MBI:CreateSpellTables()
	MBI.targetAuras = MBI.targetAuras or {}
	MBI.playerAuras = MBI.playerAuras or {}
	wipe(MBI.targetAuras)
	wipe(MBI.playerAuras)
	
	-- wrap all dots that count for combustion // ignite always counts
	local forCombu = {
		ignite = true,
	}
	for k in pairs(MBI.db.profile.threshold.forCombu) do
		if MBI.db.profile.threshold.forCombu[k] then
			forCombu[k] = true
		end
	end
	
	-- create the dot table
	for k in pairs(MBI.dotIDs) do
		local name, _, icon = GetSpellInfo(MBI.dotIDs[k])
		
		-- part of the table as an array to scan target
		table.insert(MBI.targetAuras, name)
		
		-- part of the table as a hash for storing all info about a given dot
		MBI.targetAuras[k] = {}
		MBI.targetAuras[k].name = name
		MBI.targetAuras[k].icon = icon
		if forCombu[k] then
			MBI.targetAuras[k].forCombu = true
		end
		
		-- true if warning module must include this dot
		MBI.targetAuras[k].mustWarn = false
		
		-- initialize all data we'll need later
		MBI.targetAuras[k].duration = 0
		MBI.targetAuras[k].remain = 0
		MBI.targetAuras[k].dmg = 0
		
		-- we need this to retrieve the identifier from the name
		MBI.targetAuras[name] = k
	end
	
	-- create the buff table
	for k in pairs(MBI.buffIDs) do	
		local name = GetSpellInfo(MBI.buffIDs[k])
		
		-- array
		table.insert(MBI.playerAuras, name)
		
		-- hash
		MBI.playerAuras[k] = {}
		MBI.playerAuras[k].name = name
		MBI.playerAuras[k].duration = 0
		MBI.playerAuras[k].remain = 0
		
		-- we need this to retrieve the identifier from the name
		MBI.playerAuras[name] = k
	end
end



--##############################################################################################################################################
-- frame creation / setup ----------------------------------------------------------------------------------------------------------------------

-- ignite frame setting
function MBI:SetIgniteFrame()
	-- create frames
	MBI.F.anchor = MBI.F.anchor or CreateFrame("Frame", nil, UIParent)
	MBI.F.main = MBI.F.main or CreateFrame("Frame", nil, MBI.F.anchor)
	MBI.F.power = MBI.F.power or CreateFrame("StatusBar", nil, MBI.F.main)
	MBI.F.timer = MBI.F.timer or CreateFrame("StatusBar", nil, MBI.F.main)
	MBI.F.tick = MBI.F.tick or {}
	for i = 0, 2 do
		MBI.F.tick[i] = MBI.F.tick[i] or CreateFrame("Frame", nil, MBI.F.timer)
	end

	-- set the anchor
	do
		MBI.F.anchor:SetWidth(1)
		MBI.F.anchor:SetHeight(1)
		MBI.F.anchor:SetMovable(false)
		MBI.F.anchor:EnableMouse(false)

		MBI.F.anchor:ClearAllPoints()
		local ofx = MBI.db.profile.general.anchor.coord.xcd / UIParent:GetScale() - UIParent:GetWidth() / 2
		local ofy = MBI.db.profile.general.anchor.coord.ycd / UIParent:GetScale() - UIParent:GetHeight() / 2
		MBI.F.anchor:SetPoint("CENTER", UIParent, "CENTER", ofx , ofy)

		if MBI.db.profile.general.anchor.strata == 1 then
			MBI.F.anchor:SetFrameStrata("LOW")
		elseif MBI.db.profile.general.anchor.strata == 2 then
			MBI.F.anchor:SetFrameStrata("MEDIUM")
		else
			MBI.F.anchor:SetFrameStrata("HIGH")
		end
	end

	-- ignite timer and dmg display
	do
		-- timer and dmg
		do
			MBI.F.timer.txt = MBI.F.timer.txt or MBI.F.timer:CreateFontString()
			MBI.F.timer.txt:SetFont(MBI.font, MBI.db.profile.general.layout.textSize)
			MBI.F.timer.txt:SetShadowColor(0, 0, 0, 1)
			MBI.F.timer.txt:SetShadowOffset(1, -1)

			local ofx = MBI.db.profile.ignite.layout.text.ofx
			local ofy = MBI.db.profile.ignite.layout.text.ofy
			MBI.F.timer.txt:ClearAllPoints()
			if point == "RIGHT" then
				ofx = -ofx
			end
			MBI.F.timer.txt:SetPoint(MBI.db.profile.ignite.layout.text.align, MBI.F.timer, MBI.db.profile.ignite.layout.text.align, ofx, ofy)

			MBI.F.timer.txt:SetText(MBI:FormatDamage(999999, MBI.db.profile.ignite.layout.text.format))
			local width = MBI.F.timer.txt:GetStringWidth() * 1.25
			local height = MBI.F.timer.txt:GetStringHeight() * 1.4
			MBI.F.timer.w = width
			MBI.F.timer.h = height
			MBI.F.timer.txt:SetText(MBI:FormatDamage(0, MBI.db.profile.ignite.layout.text.format))

			MBI.F.timer:SetStatusBarTexture(LSM:Fetch("statusbar", MBI.db.profile.general.layout.bar))
			MBI.F.timer:SetReverseFill(MBI.db.profile.ignite.timer.reverse)
			MBI.F.timer:SetMovable(false)
			MBI.F.timer:EnableMouse(false)

			MBI.F.timer:ClearAllPoints()
			local adjust = MBI.db.profile.ignite.layout.adjust
			if MBI.db.profile.ignite.power.enabled and MBI.db.profile.ignite.power.align == "LEFT" then
				MBI.F.timer:SetPoint("TOPRIGHT", MBI.F.main, "TOPRIGHT", -adjust, -adjust)
				MBI.F.timer:SetPoint("BOTTOMRIGHT", MBI.F.main, "BOTTOMRIGHT", -adjust, adjust)
			elseif MBI.db.profile.ignite.power.enabled and MBI.db.profile.ignite.power.align == "RIGHT" then
				MBI.F.timer:SetPoint("TOPLEFT", MBI.F.main, "TOPLEFT", adjust, -adjust)
				MBI.F.timer:SetPoint("BOTTOMLEFT", MBI.F.main, "BOTTOMLEFT", -adjust, adjust)
			else
				MBI.F.timer:SetPoint("TOPLEFT", MBI.F.main, "TOPLEFT", adjust, -adjust)
				MBI.F.timer:SetPoint("BOTTOMRIGHT", MBI.F.main, "BOTTOMRIGHT", -adjust, adjust)
			end

			MBI.F.timer:SetMinMaxValues(0, 6)
			MBI.F.timer:SetValue(0)

			MBI.F.timer:SetScript("OnUpdate", function(self, elapsed)
				if MBI.F.timer.value and MBI.F.timer.value > 0 then
					MBI.F.timer.value = MBI.F.timer.value - elapsed
					MBI.F.timer:SetValue(MBI.F.timer.value)
				end
			end)

			if MBI.cfMode then
				MBI.F.timer:SetValue(6)
			end
		end

		-- ticks marks
		do
			local size = 0.4 * MBI.F.timer.h
			MBI.F.tick.size = size
			for i = 0, 2 do
				MBI.F.tick[i]:SetMovable(false)
				MBI.F.tick[i]:EnableMouse(false)
				if MBI.db.profile.ignite.timer.reverse then
					MBI.F.tick[i]:SetBackdrop({bgFile = [[Interface\Addons\myBigIgnite\textures\tick_reverse.tga]]})
				else
					MBI.F.tick[i]:SetBackdrop({bgFile = [[Interface\Addons\myBigIgnite\textures\tick.tga]]})
				end
				if MBI.db.profile.ignite.timer.enabled and MBI.db.profile.ignite.timer.tick then
					MBI.F.tick[i]:Show()
				else
					MBI.F.tick[i]:Hide()
				end
			end
		end
	end

	-- power bar
	do
		MBI.F.power:SetStatusBarTexture(LSM:Fetch("statusbar", MBI.db.profile.general.layout.bar))
		MBI.F.power:SetOrientation("VERTICAL")
		MBI.F.power:SetRotatesTexture(true)
		MBI.F.power:SetWidth(1)
		MBI.F.power:SetHeight(1)
		MBI.F.power:SetMovable(false)
		MBI.F.power:EnableMouse(false)

		MBI.F.power:ClearAllPoints()

		if MBI.db.profile.ignite.power.align == "LEFT" then
			MBI.F.power:SetPoint("TOPLEFT", MBI.F.main, "TOPLEFT", MBI.db.profile.ignite.layout.adjust, -MBI.db.profile.ignite.layout.adjust)
			MBI.F.power:SetPoint("BOTTOMRIGHT", MBI.F.timer, "BOTTOMLEFT", -1, 0)
		else
			MBI.F.power:SetPoint("TOPRIGHT", MBI.F.main, "TOPRIGHT", -MBI.db.profile.ignite.layout.adjust, -MBI.db.profile.ignite.layout.adjust)
			MBI.F.power:SetPoint("BOTTOMLEFT", MBI.F.timer, "BOTTOMRIGHT", 1, 0)
		end

		MBI.F.power:SetMinMaxValues(0, 1)
		MBI.F.power:SetValue(0)

		MBI.F.power:SetScript("OnUpdate", function(self, elapsed)
			if MBI.F.power.endValue then
				MBI.F.power.value = MBI.F.power.value or 0
				if MBI.F.power.value > MBI.F.power.endValue then
					MBI.F.power.value = MBI.F.power.value - elapsed
					if MBI.F.power.value <= MBI.F.power.endValue then
						MBI.F.power.value = MBI.F.power.endValue
					end
					MBI.F.power:SetValue(MBI.F.power.value)
					MBI:UpdateIgnitePowerDisplay(MBI.F.power.value)
				elseif MBI.F.power.value < MBI.F.power.endValue then
					MBI.F.power.value = MBI.F.power.value + elapsed
					if MBI.F.power.value >= MBI.F.power.endValue then
						MBI.F.power.value = MBI.F.power.endValue
					end
					MBI.F.power:SetValue(MBI.F.power.value)
					MBI:UpdateIgnitePowerDisplay(MBI.F.power.value)
				end
			end
		end)

		if MBI.db.profile.ignite.power.enabled then
			MBI.F.power:Show()
		else
			MBI.F.power:Hide()
		end
	end
	
	-- main frame
	do
		MBI.F.main:ClearAllPoints()
		MBI.F.main:SetPoint(MBI.db.profile.general.anchor.align, MBI.F.anchor, "CENTER")
		MBI.F.main:SetMovable(false)
		MBI.F.main:EnableMouse(false)
		MBI.F.main:SetClampedToScreen(true)
		MBI.F.main:SetAlpha(MBI.db.profile.general.layout.alpha)

		local backdrop = {
			bgFile = LSM:Fetch("background", MBI.db.profile.general.layout.background.texture),
			edgeFile = LSM:Fetch("border", MBI.db.profile.general.layout.border.texture),
			edgeSize = MBI.db.profile.ignite.layout.bdSize,
			insets = {
				left = MBI.db.profile.ignite.layout.bgInset,
				right = MBI.db.profile.ignite.layout.bgInset,
				top = MBI.db.profile.ignite.layout.bgInset,
				bottom = MBI.db.profile.ignite.layout.bgInset,
			},
		}
		if not MBI.db.profile.general.layout.background.enabled then
			backdrop.bgFile = ""
		end
		if not MBI.db.profile.general.layout.border.enabled then
			backdrop.edgeFile = ""
		end
		MBI.F.main:SetBackdrop(backdrop)

		local border = MBI.db.profile.ignite.layout.adjust
		local width = MBI.F.timer.w * 1.25 + border * 2
		local height = MBI.F.timer.h + border * 2
		MBI.F.main.w = width
		MBI.F.main.h = height
		MBI.F.main:SetWidth(width)
		MBI.F.main:SetHeight(height)
	end

	MBI:UpdateIgniteFrame("low")
	MBI:UpdateIgniteTimerDisplay("low", 6)
	MBI:UpdateIgnitePowerDisplay(0)
end

-- on update frame
function MBI:CreateOnUpdateFrame()
	MBI.F.combat = CreateFrame("Frame", nil, MBI.F.anchor)
	MBI.F.combat:SetMovable(false)
	MBI.F.combat:EnableMouse(false)
	MBI.F.combat:SetPoint("CENTER", MBI.F.anchor, "CENTER")
	MBI.F.combat:SetScript("OnUpdate",  function(self, elapsed) MBI.MainEngine(self, elapsed) end)
	MBI.F.combat:Hide()
end

-- combustion frame
function MBI:SetCombustionFrame()
	if MBI.db.profile.modules.general.combustion.enabled then
		
		-- frame
		local frame = MBI.F.combustion or CreateFrame("Frame", nil, MBI.F.main)
		local offset = MBI.db.profile.modules.general.offset
		local framePoint, ofx, ofy = "RIGHT", -offset, 0
		if MBI.db.profile.modules.general.combustion.position == "RIGHT" then
			framePoint = "LEFT"
			ofx = offset
		elseif MBI.db.profile.modules.general.combustion.position == "TOP" then
			framePoint = "BOTTOM"
			ofx = 0
			ofy = offset
		elseif MBI.db.profile.modules.general.combustion.position == "BOTTOM" then
			framePoint = "TOP"
			ofx = 0
			ofy = -offset
		end
		frame:ClearAllPoints()
		frame:SetPoint(framePoint, MBI.F.main, MBI.db.profile.modules.general.combustion.position, ofx, ofy)
		
		frame:SetMovable(false)
		frame:EnableMouse(false)
		frame:SetWidth(MBI.F.main.h * MBI.db.profile.modules.combustion.size)
		frame:SetHeight(MBI.F.main.h * MBI.db.profile.modules.combustion.size)
		
		-- icon
		local _, _, icon = GetSpellInfo(MBI.miscIDs.combustion)
		frame.icon = frame.icon or frame:CreateTexture(nil, "Background")
		frame.icon:SetTexture(icon)
		frame.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
		frame.icon:ClearAllPoints()
		frame.icon:SetAllPoints(frame)
		
		-- dmg scrolling text
		frame.dmg = frame.dmg or {}
		for i = 1, 5 do
			frame.dmg[i] = frame.dmg[i] or CreateFrame("Frame", nil, frame)
			frame.dmg[i]:ClearAllPoints()
			frame.dmg[i]:SetAllPoints(frame)
			
			frame.dmg[i].aniGroup = frame.dmg[i].aniGroup or frame.dmg[i]:CreateAnimationGroup()
			frame.dmg[i].aniGroup:Stop()
			frame.dmg[i].slide = frame.dmg[i].slide or frame.dmg[i].aniGroup:CreateAnimation("Translation")
			frame.dmg[i].slide:SetSmoothing("OUT")
			frame.dmg[i].slide:SetOffset(0, 50)
			frame.dmg[i].aniGroup:SetScript("OnFinished", function()  
				frame.dmg[i]:Hide()
			end)
			frame.dmg[i]:Hide()
			
			frame.dmg[i].text = frame.dmg[i].text or frame.dmg[i]:CreateFontString()
			frame.dmg[i].text:ClearAllPoints()
			frame.dmg[i].text:SetPoint("TOP", frame.dmg[i], "TOP", 0, 40)
			frame.dmg[i].text:SetFont(MBI.font, frame:GetHeight() * MBI.db.profile.modules.combustion.scrollText.size, "OUTLINED")
			frame.dmg[i].text:SetJustifyH("CENTER")

			frame.dmg[i].update = frame.dmg[i].update or CreateFrame("Frame", nil, frame.dmg[i])
			frame.dmg[i].update:SetScript("OnUpdate", function(self, elapsed)
				self.lastUpdate = (self.lastUpdate or 0) + elapsed
				if self.lastUpdate > 0.1 then
					frame.dmg[i].alpha = frame.dmg[i].alpha - 0.1
					frame.dmg[i]:SetAlpha(frame.dmg[i].alpha)
					self.lastUpdate = 0
				end
			end)
			frame.dmg[i].update:Hide()
		end
		
		-- icon texts
		frame.text = frame.text or frame:CreateFontString()
		frame.text:ClearAllPoints()
		frame.text:SetPoint("TOP", frame, "TOP", MBI.db.profile.modules.combustion.iconText.dmgOfx, MBI.db.profile.modules.combustion.iconText.dmgOfy)		
		frame.text:SetJustifyH("CENTER")
		frame.text:SetTextColor(MBI:GetColor(MBI.db.profile.general.layout.iconTextColor))
		frame.text:Hide()
		
		frame.tick = frame.tick or frame:CreateFontString()
		frame.tick:ClearAllPoints()
		frame.tick:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", MBI.db.profile.modules.combustion.iconText.tickOfx, MBI.db.profile.modules.combustion.iconText.tickOfy)		
		frame.tick:SetJustifyH("CENTER")
		frame.tick:SetTextColor(MBI:GetColor(MBI.db.profile.general.layout.iconTextColor))
		frame.tick:Hide()
		
		-- timer
		frame.timer = frame.timer or CreateFrame("Statusbar", nil, frame)
		frame.timer:SetStatusBarTexture(LSM:Fetch("statusbar", MBI.db.profile.general.layout.bar))
		frame.timer:SetReverseFill(MBI.db.profile.modules.combustion.timer.reverse)
		
		local backdrop = {
			bgFile = LSM:Fetch("background", MBI.db.profile.general.layout.background.texture),
			edgeFile = "",
		}
		if not MBI.db.profile.general.layout.background.enabled then
			backdrop.bgFile = ""
		end
		frame.timer:SetBackdrop(backdrop)
		
		frame.timer:ClearAllPoints()
		local timerAlign = MBI.db.profile.modules.combustion.timer.align
		if MBI.db.profile.modules.general.combustion.position == "BOTTOM" then
			timerAlign = "bellow"
		elseif MBI.db.profile.modules.general.combustion.position == "TOP" then
			timerAlign = "above"
		end
		if timerAlign == "bellow" then
			frame.timer:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 0, -3)
			frame.timer:SetPoint("TOPRIGHT", frame, "BOTTOMRIGHT", 0, -3)
		else
			frame.timer:SetPoint("BOTTOMLEFT", frame, "TOPLEFT", 0, 3)
			frame.timer:SetPoint("BOTTOMRIGHT", frame, "TOPRIGHT", 0, 3)
		end
		
		frame.timer:SetScript("OnUpdate", function(self, elapsed)
			if frame.timer.value and frame.timer.value > 0 then
				frame.timer.value = frame.timer.value - elapsed
				frame.timer:SetValue(frame.timer.value)
				frame.timer.text:SetText(MBI:FormatTime(frame.timer.value))
				if frame.timer.value < MBI.REFRESH then
					frame.timer:Hide()
				end
			end
		end)
		
		-- timer text
		frame.timer.text = frame.timer.text or frame.timer:CreateFontString()
		frame.timer.text:SetShadowColor(0, 0, 0, 1)
		frame.timer.text:SetShadowOffset(1, -1)
		frame.timer.text:ClearAllPoints()
		if MBI.db.profile.modules.combustion.timer.reverse then
			frame.timer.text:SetPoint("LEFT", frame.timer, "LEFT")
		else
			frame.timer.text:SetPoint("RIGHT", frame.timer, "RIGHT")
		end
		
		-- cooldown
		frame.cooldown = frame.cooldown or CreateFrame("Cooldown", nil, frame)
		frame.cooldown:ClearAllPoints()
		frame.cooldown:SetAllPoints(frame)
		frame.cooldown:Hide()
		
		frame.cooldown.text = frame.cooldown.text or frame.cooldown:CreateFontString()
		frame.cooldown.text:ClearAllPoints()
		frame.cooldown.text:SetPoint("CENTER", frame.cooldown, "CENTER", 1.5, 0)		
		frame.cooldown.text:SetFont(MBI.font, frame:GetHeight() * MBI.db.profile.modules.combustion.iconText.cdSize, "OUTLINED")
		frame.cooldown.text:SetJustifyH("CENTER")
		frame.cooldown.text:SetTextColor(MBI:GetColor(MBI.db.profile.general.layout.iconTextColor))
		
		frame:Hide()
		MBI.F.combustion = frame
		
		MBI:UpdateCombustionModule("low")
		MBI.F.combustion.timer:Hide()
	end
end

-- heating up and pyro!
function MBI:SetHeatingUpFrame()
	if MBI.db.profile.modules.general.heatingup.enabled then
		local pyro, hup
		
		-- heating up
		do
			hup = MBI.F.hup or CreateFrame("Frame", nil, MBI.F.main)
			hup:SetWidth(MBI.F.main.h * MBI.db.profile.modules.heatingup.size)
			hup:SetHeight(MBI.F.main.h * MBI.db.profile.modules.heatingup.size)
			
			local texture = [[Interface\Addons\myBigIgnite\textures\]] .. MBI.db.profile.modules.heatingup.texture .. ".tga"
			hup.hl = hup.hl or hup:CreateTexture(nil, "BACKGROUND")
			hup.hl:SetTexture(texture)
			hup.hl:ClearAllPoints()
			hup.hl:SetAllPoints(hup)
			if MBI.db.profile.modules.heatingup.texture == "fire" then
				hup.hl:SetVertexColor(1, 1, 1, 0.8)
				hup.hl:SetBlendMode("BLEND")
			else
				hup.hl:SetVertexColor(1, 1, 0.7, 0.6)
				hup.hl:SetBlendMode("ADD")
			end
			if not MBI.db.profile.modules.heatingup.highlight then
				hup.hl:Hide()
			else
				hup.hl:Show()
			end
			
			local _, _, icon = GetSpellInfo(MBI.buffIDs.heatingup)
			hup.icon = hup.icon or hup:CreateTexture(nil, "ARTWORK")
			hup.icon:SetTexture(icon)
			hup.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
			local offset = 5
			if MBI.db.profile.modules.heatingup.texture == "fire" then
				offset = 6
			end
			hup.icon:ClearAllPoints()
			hup.icon:SetPoint("TOPLEFT", hup, "TOPLEFT", offset, -offset)
			hup.icon:SetPoint("BOTTOMRIGHT", hup, "BOTTOMRIGHT", -offset, offset)
			
			hup.text = hup.text or hup:CreateFontString()
			hup.text:SetFont(MBI.font, hup:GetHeight() * MBI.db.profile.modules.heatingup.text.size, "OUTLINED")
			hup.text:ClearAllPoints()
			hup.text:SetPoint(MBI.db.profile.modules.heatingup.text.anchor, hup, MBI.db.profile.modules.heatingup.text.anchor, MBI.db.profile.modules.heatingup.text.ofx, MBI.db.profile.modules.heatingup.text.ofy)
			hup.text:SetTextColor(MBI:GetColor(MBI.db.profile.general.layout.iconTextColor))
			if MBI.db.profile.modules.heatingup.text.enabled then
				hup.text:Show()
			else
				hup.text:Hide()
			end
			
			hup:SetScript("OnUpdate", function(self, elapsed)
				if hup.value and hup.value > 0 then
					hup.value = hup.value - elapsed
					hup.text:SetText(MBI:Round(hup.value, 0) .. "s")
				end
			end)
		end

		-- instant pyro
		do
			pyro = MBI.F.pyro or CreateFrame("Frame", nil, MBI.F.main)
			pyro:SetWidth(MBI.F.main.h * MBI.db.profile.modules.heatingup.size)
			pyro:SetHeight(MBI.F.main.h * MBI.db.profile.modules.heatingup.size)
			
			local texture = [[Interface\Addons\myBigIgnite\textures\]] .. MBI.db.profile.modules.heatingup.texture .. ".tga"
			pyro.hl = pyro.hl or pyro:CreateTexture(nil, "BACKGROUND")
			pyro.hl:SetTexture(texture)
			pyro.hl:ClearAllPoints()
			pyro.hl:SetAllPoints(pyro)
			if MBI.db.profile.modules.heatingup.texture == "fire" then
				pyro.hl:SetVertexColor(1, 1, 1, 0.8)
				pyro.hl:SetBlendMode("BLEND")
			else
				pyro.hl:SetVertexColor(1, 1, 0.7, 0.6)
				pyro.hl:SetBlendMode("ADD")
			end
			if not MBI.db.profile.modules.heatingup.highlight then
				pyro.hl:Hide()
			else
				pyro.hl:Show()
			end
			
			local _, _, icon = GetSpellInfo(MBI.dotIDs.pyroblast)
			pyro.icon = pyro.icon or pyro:CreateTexture(nil, "ARTWORK")
			pyro.icon:SetTexture(icon)
			pyro.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
			local offset = 5
			if MBI.db.profile.modules.heatingup.texture == "fire" then
				offset = 6
			end
			pyro.icon:ClearAllPoints()
			pyro.icon:SetPoint("TOPLEFT", pyro, "TOPLEFT", offset, -offset)
			pyro.icon:SetPoint("BOTTOMRIGHT", pyro, "BOTTOMRIGHT", -offset, offset)
			
			pyro.text = pyro.text or pyro:CreateFontString()
			pyro.text:SetFont(MBI.font, pyro:GetHeight() * MBI.db.profile.modules.heatingup.text.size, "OUTLINED")
			pyro.text:SetTextColor(MBI:GetColor(MBI.db.profile.general.layout.iconTextColor))
			pyro.text:ClearAllPoints()
			pyro.text:SetPoint(MBI.db.profile.modules.heatingup.text.anchor, pyro, MBI.db.profile.modules.heatingup.text.anchor, MBI.db.profile.modules.heatingup.text.ofx, MBI.db.profile.modules.heatingup.text.ofy)
			if MBI.db.profile.modules.heatingup.text.enabled then
				pyro.text:Show()
			else
				pyro.text:Hide()
			end
			
			pyro:SetScript("OnUpdate", function(self, elapsed)
				if pyro.value and pyro.value > 0 then
					pyro.value = pyro.value - elapsed
					pyro.text:SetText(MBI:Round(pyro.value, 0) .. "s")
				end
			end)
		end
		
		hup:Hide()
		pyro:Hide()
		MBI.F.hup = hup
		MBI.F.pyro = pyro
		
		if MBI.cfMode then
			hup:Show()
			pyro:Show()
		end
		
		MBI:UpdateHUPModule()
	end
end



--##############################################################################################################################################
-- live layout update functions ---------------------------------------------------------------------------------------------------------------

-- updates ignite frame size and color
function MBI:UpdateIgniteFrame(igtype)
	local mult = MBI.db.profile.threshold[igtype].mult or 1
	-- no scale change if heating up or bomb module enabled
	if MBI.db.profile.modules.general.heatingup.enabled or MBI.db.profile.modules.bomb.enabled then
		mult = 1
	end
	local txtSize = MBI.db.profile.general.layout.textSize * mult
	local r, g, b = MBI:GetColor(MBI.db.profile.threshold[igtype].color)

	-- background
	if MBI.db.profile.general.layout.background.enabled then
		local rb, gb, bb = r * MBI.db.profile.general.layout.background.darkness, g * MBI.db.profile.general.layout.background.darkness, b * MBI.db.profile.general.layout.background.darkness
		MBI.F.main:SetBackdropColor(rb, gb, bb)
	end
	-- border
	if MBI.db.profile.general.layout.border.enabled then
		MBI.F.main:SetBackdropBorderColor(r, g, b)
	end
	-- dmg
	MBI.F.timer.txt:SetFont(MBI.font, txtSize)
	local rt, gt, bt = r, g, b
	if MBI.db.profile.general.layout.barTextSpecificColor then
		rt, gt, bt = MBI:GetColor(MBI.db.profile.general.layout.barTextColor)
	end
	MBI.F.timer.txt:SetTextColor(rt, gt, bt)

	-- frame size
	if MBI.db.profile.ignite.power.enabled then
		MBI.F.timer:SetWidth(MBI.F.timer.w * mult)
	end
	MBI.F.main:SetWidth(MBI.F.main.w * mult)
	MBI.F.main:SetHeight(MBI.F.main.h * mult)

	-- ignite timer ticks
	if MBI.db.profile.ignite.timer.tick then
		for i = 0, 2 do
			MBI.F.tick[i]:SetWidth(MBI.F.tick.size * mult)
			MBI.F.tick[i]:SetHeight(MBI.F.tick.size * mult)
			MBI.F.tick[i]:ClearAllPoints()
			local width = MBI.F.timer.w
			if not MBI.db.profile.ignite.power.enabled then
				width = width * 1.25
			end
			if not MBI.db.profile.ignite.timer.reverse then
				MBI.F.tick[i]:SetPoint("BOTTOMLEFT", MBI.F.timer, "BOTTOMLEFT", i / 3 * width * mult, 0)
			else
				MBI.F.tick[i]:SetPoint("BOTTOMRIGHT", MBI.F.timer, "BOTTOMRIGHT", -i / 3 * width * mult, 0)
			end
			MBI.F.tick[i]:SetBackdropColor(r, g, b, MBI.db.profile.ignite.timer.alpha)
		end
	end
end

-- ignite timer bar update
function MBI:UpdateIgniteTimerDisplay(igtype, igremain)
	local r, g, b
	if igremain > MBI.db.profile.ignite.timer.redZone then
		r, g, b = MBI:GetColor(MBI.db.profile.threshold[igtype].color)
	else
		r, g, b = MBI:GetColor(MBI.db.profile.ignite.timer.redZoneColor)
	end
	MBI.F.timer:SetStatusBarColor(r, g, b, MBI.db.profile.ignite.timer.alpha)
end

-- ignite power bar update
function MBI:UpdateIgnitePowerDisplay(value)
	local r, g, b = 0, 0, 0
	local c1, c2 = 0, 0

	if value > MBI.db.profile.ignite.power.middle then
		c1 = 1 - (value - MBI.db.profile.ignite.power.middle) / (1 - MBI.db.profile.ignite.power.middle)
		c2 = 1
	else
		c1 = 1
		c2 = 1 + (value - MBI.db.profile.ignite.power.middle) / MBI.db.profile.ignite.power.middle
	end
	if MBI.db.profile.ignite.power.gradient == "rg" then
		r, g = c1, c2
	else
		b, g = c1, c2
	end
	
	MBI.F.power:SetStatusBarColor(r, g, b, MBI.db.profile.ignite.power.alpha)
end

-- combustion module update
function MBI:UpdateCombustionModule(igtype, combudmg, predicted, ticks, summary)
	local mult = MBI.db.profile.threshold[igtype].mult or 1
	local r, g, b = MBI:GetColor(MBI.db.profile.threshold[igtype].color)
	local rb, gb, bb = r * MBI.db.profile.general.layout.background.darkness, g * MBI.db.profile.general.layout.background.darkness, b * MBI.db.profile.general.layout.background.darkness
	local frame = MBI.F.combustion
	
	-- scale change if heating up or bomb module enabled can be adjusted by own combustion scaling
	if MBI.db.profile.modules.general.heatingup.enabled or MBI.db.profile.modules.bomb.enabled then
		if MBI.db.profile.modules.combustion.scaling.enabled then
			if igtype == "mid" then
				mult = MBI.db.profile.modules.combustion.scaling[igtype]
			elseif igtype == "high" then
				mult = MBI.db.profile.modules.combustion.scaling[igtype]
			end
		else
			mult = 1
		end
	end
	
	-- frame size and layout
	frame:SetWidth(MBI.F.main.h * MBI.db.profile.modules.combustion.size * mult)
	frame:SetHeight(MBI.F.main.h * MBI.db.profile.modules.combustion.size * mult)
	if frame.timer and MBI.targetAuras.combustion.remain > MBI.REFRESH then
		frame.timer:SetHeight(frame:GetHeight() / 3)
		frame.timer.text:SetFont(MBI.font, frame.timer:GetHeight() * 0.9)
		if MBI.db.profile.general.layout.barTextSpecificColor then
			frame.timer.text:SetTextColor(MBI:GetColor(MBI.db.profile.general.layout.barTextColor))
		else
			frame.timer.text:SetTextColor(r, g, b)
		end
		frame.timer:SetStatusBarColor(r, g, b)
		frame.timer:SetBackdropColor(rb, gb, bb)
		frame.timer:Show()
	end

	-- infos
	if combudmg and combudmg > 0 then
		-- scrolling text
		if not predicted and MBI.combuUpdate and not MBI.db.profile.general.autohide.combuCD then	-- not compatible with autohiding of combu frame when combu in CD
			for i = 1, 5 do
				if not frame.dmg[i].aniGroup:IsPlaying() then
					frame.dmg[i].alpha = 1
					frame.dmg[i]:SetAlpha(frame.dmg[i].alpha)
					frame.dmg[i].slide:SetDuration(2)
					frame.dmg[i].text:SetTextColor(MBI:GetColor(MBI.db.profile.modules.combustion.scrollText.color))
					frame.dmg[i].text:SetText(MBI:FormatDamage(combudmg, "condensed"))
					frame.dmg[i]:Show()
					frame.dmg[i].aniGroup:Play()
					frame.dmg[i].update:Show()
					break
				end
			end
			
		-- icon text
		elseif predicted then
			frame.text:SetFont(MBI.font, frame:GetHeight() * MBI.db.profile.modules.combustion.iconText.dmgSize, "OUTLINED")
			frame.text:SetText(MBI:FormatDamage(combudmg, "integer"))
			frame.text:Show()
			
			frame.tick:SetFont(MBI.font, frame:GetHeight() * MBI.db.profile.modules.combustion.iconText.tickSize, "OUTLINED")
			frame.tick:SetText("x" .. ticks)
			frame.tick:Show()
		end
		
	-- scrolling text
	elseif summary and not MBI.db.profile.general.autohide.combuCD then		-- not compatible with autohiding of combu frame when combu in CD
		for i = 1, 5 do
			if not frame.dmg[i].aniGroup:IsPlaying() then
				frame.dmg[i].alpha = 2	-- trick to increase time display
				frame.dmg[i]:SetAlpha(frame.dmg[i].alpha)
				local perct = MBI:Round(MBI.combuTotal / MBI.combuPredicted * 100, 0)
				if perct >= 100 then
					frame.dmg[i].text:SetTextColor(0, 1, 0)
				elseif perct >= 85 then
					frame.dmg[i].text:SetTextColor(1, 1, 0)
				else
					frame.dmg[i].text:SetTextColor(1, 0.5, 0)
				end
				frame.dmg[i].slide:SetDuration(5)
				frame.dmg[i].text:SetText(MBI:FormatDamage(MBI.combuTotal, "condensed") .. " - " .. perct .. "%")
				frame.dmg[i]:Show()
				frame.dmg[i].aniGroup:Play()
				frame.dmg[i].update:Show()
				MBI.combuTotal = 0
				MBI.combuPredicted = 0
				break
			end
		end
	end
	
	-- cooldown
	if MBI.combuCD and not MBI.db.profile.general.autohide.combuCD then	-- not compatible with autohiding of combu frame when combu in CD
		frame.text:Hide()
		frame.tick:Hide()
		if not MBI.combuCDShown then
			frame.cooldown:SetCooldown(GetTime() - MBI.combuCDTotalTime + MBI.combuCDTime, MBI.combuCDTotalTime)
			MBI.combuCDShown = true
		end
		if MBI.db.profile.modules.combustion.iconText.cdTextEnabled then
			frame.cooldown.text:SetText(MBI:FormatTime(MBI.combuCDTime))
			if MBI.combuCDTime > MBI.REFRESH then
				frame.cooldown.text:Show()
			else
				frame.cooldown.text:Hide()
			end
		end
	end
end

-- heatingup module update
function MBI:UpdateHUPModule()
	local hup = MBI.F.hup
	local pyro = MBI.F.pyro
	
	hup:ClearAllPoints()
	pyro:ClearAllPoints()
	
	local offset = MBI.db.profile.modules.general.offset - 5
	if MBI.db.profile.modules.heatingup.texture == "fire" then
		offset = MBI.db.profile.modules.general.offset - 6
	end

	if MBI.db.profile.modules.general.heatingup.position == "BOTTOM" then
		if MBI.db.profile.modules.heatingup.vertical then
			if MBI.db.profile.modules.heatingup.switch then
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset - hup:GetHeight())
				else
					pyro:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset)
				end
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset - pyro:GetHeight())
				else
					hup:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset)
				end
			else
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset - pyro:GetHeight())
				else
					hup:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset)
				end
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset - hup:GetHeight())
				else
					pyro:SetPoint("TOP", MBI.F.main, "BOTTOM", 0, -offset)
				end
			end
		else
			if MBI.db.profile.modules.heatingup.switch then
				pyro:SetPoint("TOPRIGHT", MBI.F.main, "BOTTOM", 0, -offset)
				hup:SetPoint("TOPLEFT", MBI.F.main, "BOTTOM", 0, -offset)
			else
				hup:SetPoint("TOPRIGHT", MBI.F.main, "BOTTOM", 0, -offset)
				pyro:SetPoint("TOPLEFT", MBI.F.main, "BOTTOM", 0, -offset)
			end
		end
	elseif 	MBI.db.profile.modules.general.heatingup.position == "TOP" then
		if MBI.db.profile.modules.heatingup.vertical then
			if MBI.db.profile.modules.heatingup.switch then
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset + hup:GetHeight())
				else
					pyro:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset)
				end
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset + pyro:GetHeight())
				else
					hup:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset)
				end
			else
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset + pyro:GetHeight())
				else
					hup:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset)
				end
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset + hup:GetHeight())
				else
					pyro:SetPoint("BOTTOM", MBI.F.main, "TOP", 0, offset)
				end
			end
		else
			if MBI.db.profile.modules.heatingup.switch then
				pyro:SetPoint("BOTTOMRIGHT", MBI.F.main, "TOP", 0, offset)
				hup:SetPoint("BOTTOMLEFT", MBI.F.main, "TOP", 0, offset)
			else
				hup:SetPoint("BOTTOMRIGHT", MBI.F.main, "TOP", 0, offset)
				pyro:SetPoint("BOTTOMLEFT", MBI.F.main, "TOP", 0, offset)
			end
		end
	elseif 	MBI.db.profile.modules.general.heatingup.position == "RIGHT" then
		if MBI.db.profile.modules.heatingup.vertical then
			if MBI.db.profile.modules.heatingup.switch then
				pyro:SetPoint("TOPLEFT", MBI.F.main, "RIGHT", offset, 0)
				hup:SetPoint("BOTTOMLEFT", MBI.F.main, "RIGHT", offset, 0)
			else
				hup:SetPoint("TOPLEFT", MBI.F.main, "RIGHT", offset, 0)
				pyro:SetPoint("BOTTOMLEFT", MBI.F.main, "RIGHT", offset, 0)
			end
		else
			if MBI.db.profile.modules.heatingup.switch then
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("LEFT", MBI.F.main, "RIGHT", offset + hup:GetWidth(), 0)
				else
					pyro:SetPoint("LEFT", MBI.F.main, "RIGHT", offset, 0)
				end
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("LEFT", MBI.F.main, "RIGHT", offset + pyro:GetWidth(), 0)
				else
					hup:SetPoint("LEFT", MBI.F.main, "RIGHT", offset, 0)
				end
			else
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("LEFT", MBI.F.main, "RIGHT", offset + pyro:GetWidth(), 0)
				else
					hup:SetPoint("LEFT", MBI.F.main, "RIGHT", offset, 0)
				end
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("LEFT", MBI.F.main, "RIGHT", offset + hup:GetWidth(), 0)
				else
					pyro:SetPoint("LEFT", MBI.F.main, "RIGHT", offset, 0)
				end
			end
		end
	else
		if MBI.db.profile.modules.heatingup.vertical then
			if MBI.db.profile.modules.heatingup.switch then
				pyro:SetPoint("TOPRIGHT", MBI.F.main, "LEFT", -offset, 0)
				hup:SetPoint("BOTTOMRIGHT", MBI.F.main, "LEFT", -offset, 0)
			else
				hup:SetPoint("TOPRIGHT", MBI.F.main, "LEFT", -offset, 0)
				pyro:SetPoint("BOTTOMRIGHT", MBI.F.main, "LEFT", -offset, 0)
			end
		else
			if MBI.db.profile.modules.heatingup.switch then
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset - hup:GetWidth(), 0)
				else
					pyro:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset, 0)
				end
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset - pyro:GetWidth(), 0)
				else
					hup:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset, 0)
				end
			else
				if pyro:IsVisible() and pyro:GetNumPoints() > 0 then
					hup:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset - pyro:GetWidth(), 0)
				else
					hup:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset, 0)
				end
				if hup:IsVisible() and hup:GetNumPoints() > 0 then
					pyro:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset - hup:GetWidth(), 0)
				else
					pyro:SetPoint("RIGHT", MBI.F.main, "LEFT", -offset, 0)
				end
			end
		end
	end
end	
	
	

--##############################################################################################################################################
-- core functions-------------------------------------------------------------------------------------------------------------------------------

-- combat log
function MBI:CombatLog(event, ...)
	local _, eventType, _, sourceGUID, _, _, _, destGUID, _, _, _, spellID, _, _, amount = ...
	
	if sourceGUID == UnitGUID("player") then
		-- ignite damages
		if string.find(eventType, "_DAMAGE") and spellID == MBI.dotIDs.ignite then
			local igDmg = amount

			-- target specific ignite damages
			if destGUID == UnitGUID("target") then
				-- synchro of smooth dmg display with ignite tick
				if MBI.db.profile.ignite.smoothDmgReport and not MBI.db.profile.ignite.useCombatLog then
					MBI.smoothDmg = MBI.db.profile.ignite.smoothDmgValue
				end
	
				-- ig dmg and power bar value determined by combat event
				if MBI.db.profile.ignite.useCombatLog then
					MBI.targetAuras.ignite.dmg = igDmg
					if MBI.db.profile.ignite.power.enabled then
						MBI.F.power.endValue = MBI.targetAuras.ignite.dmg / (MBI.power.average + MBI.power.sigma * 3)
						if MBI.F.power.endValue > 1 then
							MBI.F.power.endValue = 1
						end
					end	
				end
			end
			
			-- stat module
			if igDmg ~= 0 then
				if igDmg > MBI.db.profile.stats.info.ignite.highest then
					MBI.db.profile.stats.info.ignite.highest = igDmg
				elseif igDmg < MBI.db.profile.stats.info.ignite.lowest then
					MBI.db.profile.stats.info.ignite.lowest = igDmg
				end
				if igDmg > MBI.db.profile.threshold.value then
					MBI.db.profile.stats.info.ignite.supOptT = MBI.db.profile.stats.info.ignite.supOptT + 1
				elseif igDmg > MBI.db.profile.threshold.value * MBI.db.profile.threshold.interm.perct then
					MBI.db.profile.stats.info.ignite.supIntermT = MBI.db.profile.stats.info.ignite.supIntermT + 1
				end
				
				MBI.db.profile.stats.info.ignite.dmg = MBI.db.profile.stats.info.ignite.dmg + igDmg
				MBI.db.profile.stats.info.ignite.count = MBI.db.profile.stats.info.ignite.count + 1
				MBI.db.profile.stats.info.ignite.thresholdCount = MBI.db.profile.stats.info.ignite.thresholdCount + 1
				
				MBI.db.profile.stats.info.ignite.average = MBI.db.profile.stats.info.ignite.dmg / MBI.db.profile.stats.info.ignite.count
				
				if MBI.db.profile.stats.info.ignite.count > MBI.db.profile.general.resetStats * 10^6 then
					wipe(MBI.db.profile.stats.info.ignite)
					MBI:InitStatModule()
				end
			end

			-- ignite powerbar stats
			if MBI.db.profile.ignite.power.enabled then
				if igDmg ~= 0 then
					tinsert(MBI.db.profile.stats.power, igDmg)
					if #MBI.db.profile.stats.power > MBI.db.profile.ignite.power.tableSize then
						tremove(MBI.db.profile.stats.power, 1)
					end
					MBI:CalculatePower()
				end
			end
		
		-- combustion dot damages
		elseif eventType == "SPELL_PERIODIC_DAMAGE" and spellID == MBI.dotIDs.combustion then
			local combuDmg = amount
			
			-- target specific dot dmg
			if destGUID == UnitGUID("target") then
				MBI.targetAuras.combustion.dmg = combuDmg
				MBI.combuUpdate = true
			end
			
			-- total dmg for summary
			MBI.combuTick = GetTime()
			MBI.combuTotal = MBI.combuTotal + combuDmg
			
			-- stats module
			if combuDmg > 0 then
				if combuDmg > MBI.db.profile.stats.info.combustion.highestDot then
					MBI.db.profile.stats.info.combustion.highestDot = combuDmg
				elseif combuDmg < MBI.db.profile.stats.info.combustion.lowestDot then
					MBI.db.profile.stats.info.combustion.lowestDot = combuDmg
				end
				
				MBI.db.profile.stats.info.combustion.dmgDot = MBI.db.profile.stats.info.combustion.dmgDot + combuDmg
				MBI.db.profile.stats.info.combustion.countDot = MBI.db.profile.stats.info.combustion.countDot + 1
				MBI.db.profile.stats.info.combustion.averageDot = MBI.db.profile.stats.info.combustion.dmgDot / MBI.db.profile.stats.info.combustion.countDot
				
				if MBI.db.profile.stats.info.combustion.countDot > MBI.db.profile.general.resetStats * 10^6 then
					wipe(MBI.db.profile.stats.info.combustion.countDot)
					MBI:InitStatModule()
				end
			end
		
		-- combustion direct damages for stats
		elseif eventType == "SPELL_DAMAGE" and spellID == MBI.miscIDs.combustion then
			local combuDmg = amount
			
			if combuDmg > 0 then
				if combuDmg > MBI.db.profile.stats.info.combustion.highestDirect then
					MBI.db.profile.stats.info.combustion.highestDirect = combuDmg
				elseif combuDmg < MBI.db.profile.stats.info.combustion.lowestDirect then
					MBI.db.profile.stats.info.combustion.lowestDirect = combuDmg
				end
				
				MBI.db.profile.stats.info.combustion.dmgDirect = MBI.db.profile.stats.info.combustion.dmgDirect + combuDmg
				MBI.db.profile.stats.info.combustion.countDirect = MBI.db.profile.stats.info.combustion.countDirect + 1
				MBI.db.profile.stats.info.combustion.averageDirect = MBI.db.profile.stats.info.combustion.dmgDirect / MBI.db.profile.stats.info.combustion.countDirect
				
				if MBI.db.profile.stats.info.combustion.countDirect > MBI.db.profile.general.resetStats * 10^6 then
					wipe(MBI.db.profile.stats.info.combustion.countDirect)
					MBI:InitStatModule()
				end
			end
		end
	end	
end

-- power bar numbers update
function MBI:CalculatePower()
	local average = 0
	local sigma = 0
	for i = 1, #MBI.db.profile.stats.power do
		average = average + MBI.db.profile.stats.power[i]
	end
	average = average / #MBI.db.profile.stats.power
	for i = 1, #MBI.db.profile.stats.power do
		sigma = sigma + (MBI.db.profile.stats.power[i] - average)^2
	end
	sigma = math.sqrt(sigma / #MBI.db.profile.stats.power)
	
	MBI.power.average = average
	MBI.power.sigma = sigma
end

-- main engine : aura tracking / damage fetching / timers / ...
function MBI:MainEngine(elapsed)
	self.lastUpdate = (self.lastUpdate or 0) + elapsed
	if self.lastUpdate > MBI.REFRESH then
		local time = GetTime()
		local igType = "low"
		local isDotAbsent = false
		local isTarget = UnitGUID("target")

		-- scanning of target for dots
		for i = 1, #MBI.targetAuras do
			local name, _, _, _, _, duration, expTime, _, _, _, _, _, _, _, val1 = UnitDebuff("target", MBI.targetAuras[i], nil, "PLAYER")
			local identifier = MBI.targetAuras[MBI.targetAuras[i]]
			
			if name then
				-- determine time remaining specifically for a given dot tracked
				if expTime ~= nil then
					MBI.targetAuras[identifier].remain = expTime - time
					if MBI.targetAuras[identifier].remain <= 0 then
						MBI.targetAuras[identifier].remain = 0
					end
				else
					MBI.targetAuras[identifier].remain = 0
				end
				MBI.targetAuras[identifier].duration = duration
				
				-- checks if time > refresh for each DoT implicated in combu
				if MBI.targetAuras[identifier].remain < MBI.REFRESH and MBI.targetAuras[identifier].forCombu then
					isDotAbsent = true
				end
				
				-- store dmg value for ignite
				if identifier == "ignite" and not MBI.db.profile.ignite.useCombatLog then
					if MBI.targetAuras.ignite.remain < MBI.REFRESH or not MBI.inCombat or not val1 then
						MBI.targetAuras.ignite.dmg = 0
						MBI.targetAuras.ignite.remain = 0
						MBI.smoothDmg = 0
					elseif MBI.db.profile.ignite.smoothDmgReport then
						if MBI.smoothDmg >= MBI.db.profile.ignite.smoothDmgValue then
							MBI.targetAuras.ignite.dmg = val1
							MBI.smoothDmg = 0
						end
						MBI.smoothDmg = MBI.smoothDmg + MBI.REFRESH
					else
						MBI.targetAuras.ignite.dmg = val1
					end
				end
			else
				MBI.targetAuras[identifier].remain = 0
				MBI.targetAuras[identifier].duration = 0
				if not (identifier == "combustion" and MBI.combuUpdate) then		-- we protect last tick of combu to be erased before being displayed
					MBI.targetAuras[identifier].dmg = 0
				end
				if MBI.targetAuras[identifier].forCombu then
					isDotAbsent = true
				end
			end
		end

		-- ignite dmg report
		if MBI.db.profile.ignite.dmgAsDps then
			MBI.F.timer.txt:SetText(MBI:FormatDamage(MBI:Round(MBI.targetAuras.ignite.dmg / 2, 0), MBI.db.profile.ignite.layout.text.format))
		else
			MBI.F.timer.txt:SetText(MBI:FormatDamage(MBI.targetAuras.ignite.dmg, MBI.db.profile.ignite.layout.text.format))
		end

		-- power bar
		if MBI.db.profile.ignite.power.enabled and not MBI.db.profile.ignite.useCombatLog then
			MBI.F.power.endValue = MBI.targetAuras.ignite.dmg / (MBI.power.average + MBI.power.sigma * 3)
			if MBI.F.power.endValue > 1 then
				MBI.F.power.endValue = 1
			end
		end
		
		-- get combustion CD remaining
		MBI:CombuCheck()
		
		-- frame fading depending on ignite remaining time
		if MBI.targetAuras.ignite.remain < MBI.REFRESH and MBI.db.profile.general.autohide.noIgnite then
			MBI.F.main:Hide()
		else
			MBI.F.main:Show()
		end
		-- frame hiding if display w/o ignite is enabled but player has no target
		if not isTarget and MBI.db.profile.general.autohide.noCombat then
			MBI.F.main:Hide()
		end
		-- frame hiding if combu in CD and frame hiding enabled
		if MBI.db.profile.general.autohide.combuCD and MBI.combuCD and MBI.combuCDTime >= MBI.db.profile.general.autohide.combuCDTime then
			MBI.F.main:Hide()
		end

		-- updates frame display in function of DoTs / ignite dmg
		if not MBI.combuCD and not isDotAbsent then
			if MBI.targetAuras.ignite.dmg >= MBI.db.profile.threshold.value then
				igType = "high"
			elseif MBI.targetAuras.ignite.dmg >= MBI.db.profile.threshold.value * MBI.db.profile.threshold.interm.perct and MBI.db.profile.threshold.interm.enabled then
				igType = "mid"
			end
		end
		MBI:UpdateIgniteFrame(igType)
		
		-- timer bar
		if MBI.db.profile.ignite.timer.enabled then
			if MBI.targetAuras.ignite.remain > MBI.REFRESH then
				MBI.F.timer.value = MBI.targetAuras.ignite.remain
				MBI.F.timer:SetValue(MBI.targetAuras.ignite.remain)
				MBI:UpdateIgniteTimerDisplay(igType, MBI.targetAuras.ignite.remain)
			else
				MBI.F.timer.value = 0
				MBI.F.timer:SetValue(0)
				MBI:UpdateIgniteTimerDisplay("low", 0)
			end
		end
		
		-- combustion module
		if MBI.db.profile.modules.general.combustion.enabled then
			if MBI.combuCD then
				if MBI.combuTotal > 0 and MBI.combuPredicted > 0 and MBI.combuTick and time - MBI.combuTick > 2 then		-- base tick interval is 1 sec so we are large
					MBI:UpdateCombustionModule(igType, 0, nil, nil, true)
					MBI.combuTick = nil
				else
					MBI:UpdateCombustionModule(igType, MBI.targetAuras.combustion.dmg)
					MBI.F.combustion.timer.value = MBI.targetAuras.combustion.remain
					MBI.F.combustion.timer:SetMinMaxValues(0, MBI.targetAuras.combustion.duration)
					MBI.F.combustion.timer:SetValue(MBI.F.combustion.timer.value)
					if MBI.F.combustion.timer.value == 0 then
						MBI.F.combustion.timer:Hide()
					else
						MBI.F.combustion.timer:Show()
					end
				end
				MBI.F.combustion:Show()
			elseif igType ~= "low" or (igType == "low" and MBI.db.profile.modules.combustion.low and MBI.targetAuras.ignite.dmg > 0) then
				local baseTick = 10	-- unhasted combu has 10 ticks
				local hastedTick = MBI:BankerRound(baseTick * (1 + GetRangedHaste() / 100))		-- half to even rounding is used in haste calculation
				if MBI.combuGlyphed then	-- glyph of combustion active
					hastedTick = hastedTick * 2
				end
				MBI.combuPredicted = hastedTick * MBI.targetAuras.ignite.dmg * (1 + GetSpellCritChance(3) / 100) * 0.2
				MBI:UpdateCombustionModule(igType, MBI.combuPredicted, true, hastedTick)
				MBI.F.combustion:Show()
			else
				MBI:UpdateCombustionModule(igType, 0)
				if MBI.combuBeforeHiding <= 0 then		-- delay here is to let omniCC animations and similar to finish before hiding combu frame
					MBI.F.combustion:Hide()
				else
					MBI.combuBeforeHiding = MBI.combuBeforeHiding - MBI.REFRESH
				end
			end
		end
		MBI.combuUpdate = false
		
		-- scanning of player for buffs
		for i = 1, #MBI.playerAuras do
			local name, _, _, _, _, duration, expTime = UnitBuff("player", MBI.playerAuras[i], nil, "PLAYER")
			local identifier = MBI.playerAuras[MBI.playerAuras[i]]
			
			if name then
				if expTime ~= nil then
					MBI.playerAuras[identifier].remain = expTime - time
					if MBI.playerAuras[identifier].remain <= 0 then
						MBI.playerAuras[identifier].remain = 0
					end
				else
					MBI.playerAuras[identifier].remain = 0
				end
				MBI.playerAuras[identifier].duration = duration
			else
				MBI.playerAuras[identifier].remain = 0
				MBI.playerAuras[identifier].duration = 0
			end
		end
		
		-- heating up and pyro! module
		if MBI.db.profile.modules.general.heatingup.enabled then
			-- heating up
			if MBI.db.profile.modules.general.heatingup.show == "both" or MBI.db.profile.modules.general.heatingup.show == "hup" then
				if MBI.playerAuras.heatingup.remain > MBI.REFRESH and not MBI.db.profile.modules.heatingup.showHUPAlways and not MBI:InfernoCheck() then
					MBI.F.hup.value = MBI.playerAuras.heatingup.remain
					MBI.F.hup:Show()
				elseif
					MBI.playerAuras.heatingup.remain > MBI.REFRESH and MBI.db.profile.modules.heatingup.showHUPAlways then
					MBI.F.hup.value = MBI.playerAuras.heatingup.remain
					MBI.F.hup:Show()
				else
					MBI.F.hup:Hide()
				end
			end
			
			-- pyro!
			if MBI.db.profile.modules.general.heatingup.show == "both" or MBI.db.profile.modules.general.heatingup.show == "pyro" then
				if MBI.playerAuras.instapyro.remain > MBI.REFRESH then
					MBI.F.pyro.value = MBI.playerAuras.instapyro.remain
					MBI.F.pyro:Show()
				else
					MBI.F.pyro:Hide()
				end
			end
			
			MBI:UpdateHUPModule()
		end
		
		-- stops the on update code after 5 sec out of combat / no combustion in CD
		if not MBI.inCombat then
			-- autohide
			if MBI.db.profile.general.autohide.noCombat and not MBI.cfMode then
				MBI.F.main:Hide()
			else
				MBI.F.main:Show()
			end

			-- frame display
			MBI:UpdateIgniteFrame(igType)
			
			-- heating up module
			if MBI.db.profile.modules.general.heatingup.enabled then
				MBI.F.hup:Hide()
				MBI.F.pyro:Hide()
			end
			
			-- should stop scrolling text and reset it if hidden before the end
			if MBI.db.profile.modules.general.combustion.enabled and MBI.F.combustion then
				for i = 1, 5 do
					if MBI.F.combustion.dmg[i].aniGroup:IsPlaying() then
						MBI.F.combustion.dmg[i].aniGroup:Stop()
						MBI.F.combustion.dmg[i].update:Hide()
						MBI.F.combustion.dmg[i]:Hide()
					end
				end
			end
			
			-- stop on update after MBI.time_before_stop_onupdate
			if not MBI.combuCD then
				MBI.time_before_stop_onupdate = MBI.time_before_stop_onupdate - MBI.REFRESH
				if MBI.time_before_stop_onupdate < 0 then
					MBI.F.combat:Hide()
					MBI:UnregisterEvent("COMBAT_LOG_EVENT_UNFILTERED")
					MBI.time_before_stop_onupdate = 10
					MBI.smoothDmg = 0
				end
			end
		end
		
		self.lastUpdate = 0
	end
end



--##############################################################################################################################################
-- helper functions ----------------------------------------------------------------------------------------------------------------------------

-- UI scale change detection
function MBI:ScaleChange()
	local UIScale = UIParent:GetScale()
	MBI.db.profile.general.anchor.coord.xcd = MBI.F.anchor:GetLeft() * UIScale
	MBI.db.profile.general.anchor.coord.ycd = MBI.F.anchor:GetBottom() * UIScale
	if MBI.configLoaded then
		wipe(MBI.options.args)
		MBI:LoadFireOptions()
		MBI:ChangeConfigDisplay("fireSpec")
	end
end

-- Combu glyph detection
function MBI:CombuGlyphed()
	MBI.combuGlyphed = false
	for i = 1, NUM_GLYPH_SLOTS do
		local enabled, glyphType, _, glyphID, icon = GetGlyphSocketInfo(i)
		if enabled and glyphType == 1 then	-- 1 is for major glyph
			if glyphID and glyphID == 56368	then	-- combu glyph id
				MBI.combuGlyphed = true
			end
		end
	end
end

-- combustion CD check function
function MBI:CombuCheck()
	local startCD, durationCD = GetSpellCooldown(MBI.miscIDs.combustion)
	local time = GetTime()
	if time > startCD + durationCD then
		MBI.combuCD = false
		MBI.combuCDTime = 0
		MBI.combuCDShown = false
		MBI.combuTotal = 0
		if MBI.F.combustion and MBI.F.combustion.cooldown.text then
			MBI.F.combustion.cooldown.text:Hide()
		end
	else
		MBI.combuCD = true
		MBI.combuCDTime = startCD + durationCD - time
		MBI.combuCDTotalTime = durationCD
		MBI.combuBeforeHiding = 1
		MBI.F.combat:Show()
	end
end

-- inferno CD check
function MBI:InfernoCheck()
	local startCD, durationCD = GetSpellCooldown(MBI.miscIDs.inferno)
	local time = GetTime()
	local inCD = false
	
	if time < startCD + durationCD and durationCD > 2 then
		inCD = true
	end
	
	return inCD
end

-- combat check function
function MBI:CombatCheck(event)
	if event == "PLAYER_REGEN_DISABLED" then
		MBI.F.combat:Show()
		MBI:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED", "CombatLog")
		if MBI.F.info and MBI.F.info:IsShown() then
			MBI.F.info:Hide()
		end
		MBI.inCombat = true
		ACR:NotifyChange("myBigIgnite")
	else
		MBI.inCombat = false
		ACR:NotifyChange("myBigIgnite")
		if MBI.db.profile.threshold.value == 0 then
			print(MBI.ORANGE .. L["myBigIgnite: "] .. MBI.YELLOW_LIGHT .. L["notyetthreshold"])
			UIErrorsFrame:AddMessage(MBI.ORANGE .. L["notyetthreshold"])
		end
	end
end

-- command parser
function MBI:CmdParser(cmd)
	if cmd == "config" then
		MBI:OpenConfig()
	elseif string.find(cmd, "threshold") then
		local threshold = string.match(cmd, " (%d+)")
		if threshold then
			MBI.db.profile.threshold.value = tonumber(string.match(cmd, " (%d+)"))
			MBI.db.profile.stats.info.ignite.thresholdCount = 0
			MBI.db.profile.stats.info.ignite.supOptT = 0
			MBI.db.profile.stats.info.ignite.supIntermT = 0
			if MBI.F.info and MBI.F.info:IsShown() and MBI.infoTable.type == "stats" then
				MBI:PopulateInfo("stats")
				MBI:InfoScrollUpdate()
			end
			ACR:NotifyChange("myBigIgnite")
		else
			print(format(L["%senter a positive number"], MBI:HlString(L["myBigIgnite: "], MBI.ORANGE, MBI.NORMAL)))
		end
	elseif cmd == "help" or cmd == "stats" then
		MBI:OpenInfo(cmd, true)
	else
		print(MBI.ORANGE .. "myBigIgnite v" .. MBI.VERSION .. " | Istaran - Medivh EU.")
		print(MBI.YELLOW_LIGHT .. L["/mbi help to obtain infos."])
	end
end

